/*     */ package com.zimbra.cs.fb;
/*     */ 
/*     */ import com.zimbra.common.calendar.ICalTimeZone;
/*     */ import com.zimbra.common.calendar.ParsedDateTime;
/*     */ import com.zimbra.common.calendar.TimeZoneMap;
/*     */ import com.zimbra.common.calendar.ZCalendar.ICalTok;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZComponent;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZParameter;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZProperty;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.cs.ldap.LdapUtil;
/*     */ import com.zimbra.cs.mailbox.calendar.IcalXmlStrMap;
/*     */ import com.zimbra.cs.mailbox.calendar.Invite;
/*     */ import com.zimbra.cs.mailbox.calendar.Period;
/*     */ import com.zimbra.cs.mailbox.calendar.ZOrganizer;
/*     */ import java.io.IOException;
/*     */ import java.io.StringWriter;
/*     */ import java.text.ParseException;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Iterator;
/*     */ import java.util.LinkedHashSet;
/*     */ import java.util.List;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class FreeBusy
/*     */   implements Iterable<Interval>
/*     */ {
/*     */   private String mName;
/*     */   protected IntervalList mList;
/*     */   private long mStart;
/*     */   private long mEnd;
/*     */   public static final String FBTYPE_FREE = "FREE";
/*     */   public static final String FBTYPE_BUSY = "BUSY";
/*     */   public static final String FBTYPE_BUSY_TENTATIVE = "BUSY-TENTATIVE";
/*     */   public static final String FBTYPE_BUSY_UNAVAILABLE = "BUSY-UNAVAILABLE";
/*     */   public static final String FBTYPE_NODATA = "X-ZIMBRA-FREEBUSY-NODATA";
/*     */   public static final String FBTYPE_OUTLOOK_FREE = "FREE";
/*     */   public static final String FBTYPE_OUTLOOK_BUSY = "BUSY";
/*     */   public static final String FBTYPE_OUTLOOK_TENTATIVE = "TENTATIVE";
/*     */   public static final String FBTYPE_OUTLOOK_OUTOFOFFICE = "OOF";
/*     */   private static String[] sBusyOrder;
/*     */   private static final String NL = "\r\n";
/*     */   private static final String MAILTO = "mailto:";
/*     */   private static final String HTTP = "http:";
/*     */   
/*     */   public static FreeBusy emptyFreeBusy(String name, long start, long end)
/*     */   {
/*  58 */     return new FreeBusy(name, start, end);
/*     */   }
/*     */   
/*     */   public static FreeBusy nodataFreeBusy(String name, long start, long end) {
/*  62 */     IntervalList il = new IntervalList(start, end);
/*  63 */     if (!LC.freebusy_disable_nodata_status.booleanValue())
/*  64 */       il.addInterval(new Interval(start, end, "N"));
/*  65 */     return new FreeBusy(name, il, start, end);
/*     */   }
/*     */   
/*  68 */   protected FreeBusy(String name, long start, long end) { this(name, new IntervalList(start, end), start, end); }
/*     */   
/*     */   protected FreeBusy(String name, IntervalList list, long start, long end) {
/*  71 */     this.mName = name;
/*  72 */     this.mList = list;
/*  73 */     this.mStart = start;
/*  74 */     this.mEnd = end;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private static class IntervalIterator
/*     */     implements Iterator<FreeBusy.Interval>
/*     */   {
/*     */     private FreeBusy.Interval mCur;
/*     */     
/*     */ 
/*  85 */     private IntervalIterator(FreeBusy.IntervalList list) { this.mCur = list.getHead(); }
/*     */     
/*  87 */     public boolean hasNext() { return this.mCur != null; }
/*     */     
/*  89 */     public FreeBusy.Interval next() { FreeBusy.Interval toRet = this.mCur;
/*  90 */       this.mCur = this.mCur.getNext();
/*  91 */       return toRet;
/*     */     }
/*     */     
/*  94 */     public void remove() { throw new IllegalArgumentException("Unsupported"); }
/*     */   }
/*     */   
/*     */   public String getName()
/*     */   {
/*  99 */     return this.mName;
/*     */   }
/*     */   
/*     */ 
/* 103 */   public Iterator<Interval> iterator() { return new IntervalIterator(this.mList, null); }
/*     */   
/*     */   protected static class IntervalList implements Iterable<FreeBusy.Interval> { long mStart;
/*     */     long mEnd;
/*     */     FreeBusy.Interval mHead;
/*     */     
/* 109 */     public Iterator<FreeBusy.Interval> iterator() { return new FreeBusy.IntervalIterator(this, null); }
/*     */     
/*     */     IntervalList(long start, long end)
/*     */     {
/* 113 */       this.mStart = start;
/* 114 */       this.mEnd = end;
/* 115 */       this.mHead = new FreeBusy.Interval(start, end, "F");
/*     */     }
/*     */     
/*     */     public void addInterval(FreeBusy.Interval toAdd) {
/* 119 */       assert (toAdd.mStart <= toAdd.mEnd);
/*     */       
/* 121 */       if (toAdd.mStart < this.mStart) {
/* 122 */         toAdd.mStart = this.mStart;
/*     */       }
/* 124 */       if (toAdd.mEnd > this.mEnd) {
/* 125 */         toAdd.mEnd = this.mEnd;
/*     */       }
/*     */       
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 137 */       for (FreeBusy.Interval uberStart = this.mHead; uberStart.hasNext(); uberStart = uberStart.getNext())
/*     */       {
/* 139 */         if (uberStart.getNext().mStart > toAdd.mStart) {
/*     */           break;
/*     */         }
/*     */       }
/* 143 */       assert (uberStart.mStart <= toAdd.mStart);
/* 144 */       assert (uberStart.overlapsOrAbuts(toAdd));
/*     */       
/* 146 */       FreeBusy.Interval cur = uberStart;
/*     */       
/* 148 */       while (toAdd.mStart < toAdd.mEnd) {
/* 149 */         assert (cur.mEnd >= cur.mStart);
/* 150 */         assert (cur.mStart <= toAdd.mStart);
/*     */         
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 167 */         if (toAdd.mStart > cur.mStart) {
/* 168 */           FreeBusy.Interval newInt = new FreeBusy.Interval(toAdd.mStart, cur.mEnd, cur.mStatus, cur.getInstances());
/*     */           
/*     */ 
/* 171 */           cur.insertAfter(newInt);
/* 172 */           cur.mEnd = newInt.mStart;
/* 173 */           cur = newInt;
/*     */         }
/*     */         
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 191 */         if (toAdd.mEnd < cur.mEnd) {
/* 192 */           FreeBusy.Interval afterUs = new FreeBusy.Interval(toAdd.mEnd, cur.mEnd, cur.mStatus, cur.getInstances());
/*     */           
/*     */ 
/* 195 */           cur.insertAfter(afterUs);
/* 196 */           cur.mEnd = toAdd.mEnd;
/*     */         }
/*     */         
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 208 */         cur.combineStatus(toAdd.mStatus);
/* 209 */         cur.addInstances(toAdd.getInstances());
/*     */         
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 220 */         toAdd.mStart = cur.mEnd;
/*     */         
/* 222 */         if (cur.mNext != null) {
/* 223 */           cur = cur.mNext;
/*     */         }
/* 225 */         else if ((!$assertionsDisabled) && (toAdd.mStart != toAdd.mEnd)) { throw new AssertionError();
/*     */         }
/*     */       }
/*     */       
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 234 */       cur = uberStart;
/* 235 */       if (cur.hasPrev()) {
/* 236 */         cur = cur.getPrev();
/*     */       }
/*     */       
/* 239 */       while (cur.getNext() != null) {
/* 240 */         assert (cur.getNext().mStart == cur.mEnd);
/* 241 */         if (cur.mStatus.equals(cur.getNext().mStatus)) {
/* 242 */           cur.mEnd = cur.getNext().mEnd;
/* 243 */           cur.mInstances.addAll(cur.getNext().mInstances);
/* 244 */           cur.removeNext();
/*     */         } else {
/* 246 */           cur = cur.getNext();
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */     public String toString()
/*     */     {
/* 255 */       StringBuilder toRet = new StringBuilder("\n");
/* 256 */       for (FreeBusy.Interval cur = this.mHead; cur != null; cur = cur.getNext()) {
/* 257 */         toRet.append("\t").append(cur.toString()).append("\n");
/*     */       }
/* 259 */       return toRet.toString();
/*     */     }
/*     */     
/* 262 */     public FreeBusy.Interval getHead() { return this.mHead; }
/*     */   }
/*     */   
/*     */ 
/*     */   public static class Interval
/*     */   {
/*     */     long mStart;
/*     */     long mEnd;
/*     */     
/*     */     public Interval(long start, long end, String status)
/*     */     {
/* 273 */       this.mStart = start;
/* 274 */       this.mEnd = end;
/* 275 */       assert (end >= start);
/* 276 */       if (status != null) {
/* 277 */         this.mStatus = status;
/*     */       } else {
/* 279 */         this.mStatus = "F";
/*     */       }
/* 281 */       this.mInstances = new LinkedHashSet();
/*     */     }
/*     */     
/*     */     public Interval(long start, long end, String status, FreeBusy.FBInstance instance) {
/* 285 */       this(start, end, status);
/* 286 */       if (instance != null)
/* 287 */         this.mInstances.add(instance);
/*     */     }
/*     */     
/*     */     public Interval(long start, long end, String status, LinkedHashSet<FreeBusy.FBInstance> instances) {
/* 291 */       this(start, end, status);
/* 292 */       addInstances(instances);
/*     */     }
/*     */     
/*     */     public String toString() {
/* 296 */       StringBuilder toRet = new StringBuilder();
/* 297 */       toRet.append("start=").append(this.mStart);
/* 298 */       toRet.append(", end=").append(this.mEnd);
/* 299 */       toRet.append(", status=").append(this.mStatus);
/* 300 */       toRet.append(", invites=[");
/* 301 */       int i = 0;
/* 302 */       for (FreeBusy.FBInstance instance : this.mInstances) {
/* 303 */         if (i > 0)
/* 304 */           toRet.append(", ");
/* 305 */         i++;
/* 306 */         toRet.append(instance.toString());
/*     */       }
/* 308 */       toRet.append("]");
/* 309 */       return toRet.toString();
/*     */     }
/*     */     
/*     */ 
/*     */ 
/* 314 */     Interval mNext = null;
/* 315 */     Interval mPrev = null;
/*     */     
/*     */     String mStatus;
/*     */     LinkedHashSet<FreeBusy.FBInstance> mInstances;
/*     */     
/*     */     void insertAfter(Interval other)
/*     */     {
/* 322 */       other.mNext = this.mNext;
/* 323 */       other.mPrev = this;
/* 324 */       if (this.mNext != null) {
/* 325 */         this.mNext.mPrev = other;
/*     */       }
/* 327 */       this.mNext = other;
/*     */     }
/*     */     
/*     */     void removeNext() {
/* 331 */       this.mNext = this.mNext.getNext();
/* 332 */       if (this.mNext != null) {
/* 333 */         this.mNext.mPrev = this;
/*     */       }
/*     */     }
/*     */     
/*     */     void addInstances(LinkedHashSet<FreeBusy.FBInstance> instances) {
/* 338 */       if (instances != null) {
/* 339 */         this.mInstances.addAll(instances);
/*     */       }
/*     */     }
/*     */     
/*     */     void combineStatus(String otherStatus) {
/* 344 */       this.mStatus = FreeBusy.chooseBusier(this.mStatus, otherStatus);
/*     */     }
/*     */     
/* 347 */     public long getStart() { return this.mStart; }
/* 348 */     public long getEnd() { return this.mEnd; }
/* 349 */     public String getStatus() { return this.mStatus; }
/* 350 */     public LinkedHashSet<FreeBusy.FBInstance> getInstances() { return this.mInstances; }
/*     */     
/*     */ 
/*     */ 
/* 354 */     public boolean overlapsOrAbuts(Interval other) { return (other.mEnd >= this.mStart) && (other.mStart <= this.mEnd); }
/*     */     
/* 356 */     public boolean hasPrev() { return this.mPrev != null; }
/* 357 */     public Interval getPrev() { return this.mPrev; }
/* 358 */     public boolean hasNext() { return this.mNext != null; }
/* 359 */     public Interval getNext() { return this.mNext; }
/*     */     
/* 361 */     void setStatus(String status) { this.mStatus = status; }
/*     */   }
/*     */   
/*     */   public String getBusiest() {
/* 365 */     String val = "F";
/* 366 */     for (Iterator<Interval> iter = iterator(); iter.hasNext();) {
/* 367 */       Interval interval = (Interval)iter.next();
/* 368 */       val = chooseBusier(val, interval.getStatus());
/*     */     }
/* 370 */     return val;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   static
/*     */   {
/* 388 */     sBusyOrder = new String[5];
/*     */     
/*     */ 
/*     */ 
/* 392 */     sBusyOrder[0] = "O";
/* 393 */     sBusyOrder[1] = "B";
/* 394 */     sBusyOrder[2] = "T";
/* 395 */     sBusyOrder[3] = "N";
/* 396 */     sBusyOrder[4] = "F";
/*     */   }
/*     */   
/*     */   public static String chooseBusier(String freeBusy1, String freeBusy2) {
/* 400 */     for (int i = 0; i < sBusyOrder.length; i++) {
/* 401 */       String busy = sBusyOrder[i];
/* 402 */       if (busy.equals(freeBusy1))
/* 403 */         return freeBusy1;
/* 404 */       if (busy.equals(freeBusy2))
/* 405 */         return freeBusy2;
/*     */     }
/* 407 */     if (freeBusy1 != null) {
/* 408 */       return freeBusy1;
/*     */     }
/* 410 */     return freeBusy2;
/*     */   }
/*     */   
/*     */   public static enum Method {
/* 414 */     PUBLISH,  REQUEST,  REPLY;
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */     private Method() {}
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public String toVCalendar(Method m, String organizer, String attendee, String url)
/*     */   {
/* 427 */     if ((m == null) || (organizer == null)) {
/* 428 */       throw new IllegalArgumentException("missing method or organizer");
/*     */     }
/* 430 */     ParsedDateTime now = ParsedDateTime.fromUTCTime(System.currentTimeMillis());
/* 431 */     ParsedDateTime startTime = ParsedDateTime.fromUTCTime(this.mStart);
/* 432 */     ParsedDateTime endTime = ParsedDateTime.fromUTCTime(this.mEnd);
/*     */     
/* 434 */     StringBuilder toRet = new StringBuilder("BEGIN:VCALENDAR").append("\r\n");
/* 435 */     toRet.append("PRODID:").append("Zimbra-Calendar-Provider").append("\r\n");
/* 436 */     toRet.append("VERSION:").append("2.0").append("\r\n");
/* 437 */     toRet.append("METHOD:").append(m.name()).append("\r\n");
/* 438 */     toRet.append("BEGIN:VFREEBUSY").append("\r\n");
/*     */     
/* 440 */     toRet.append("ORGANIZER:");
/* 441 */     if ((!organizer.toLowerCase().startsWith("mailto:")) && (!organizer.toLowerCase().startsWith("http:")))
/* 442 */       toRet.append("mailto:");
/* 443 */     toRet.append(organizer).append("\r\n");
/* 444 */     if (attendee != null) {
/* 445 */       toRet.append("ATTENDEE:");
/* 446 */       if ((!attendee.toLowerCase().startsWith("mailto:")) && (!attendee.toLowerCase().startsWith("http:")))
/* 447 */         toRet.append("mailto:");
/* 448 */       toRet.append(attendee).append("\r\n");
/*     */     }
/* 450 */     toRet.append("DTSTAMP:").append(now.toString()).append("\r\n");
/* 451 */     toRet.append("DTSTART:").append(startTime.toString()).append("\r\n");
/* 452 */     toRet.append("DTEND:").append(endTime.toString()).append("\r\n");
/* 453 */     if (url != null) {
/* 454 */       toRet.append("URL:").append(url).append("\r\n");
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 468 */     for (Iterator<Interval> iter = iterator(); iter.hasNext();) {
/* 469 */       Interval cur = (Interval)iter.next();
/* 470 */       String status = cur.getStatus();
/*     */       
/* 472 */       if ((!status.equals("F")) && 
/*     */       
/* 474 */         (!status.equals("N")))
/*     */       {
/*     */ 
/* 477 */         if (status.equals("B")) {
/* 478 */           toRet.append("FREEBUSY;FBTYPE=BUSY:");
/* 479 */         } else if (status.equals("T")) {
/* 480 */           toRet.append("FREEBUSY;FBTYPE=BUSY-TENTATIVE:");
/* 481 */         } else if (status.equals("O")) {
/* 482 */           toRet.append("FREEBUSY;FBTYPE=BUSY-UNAVAILABLE:");
/*     */         } else {
/* 484 */           if (!$assertionsDisabled) throw new AssertionError();
/* 485 */           toRet.append(":");
/*     */         }
/*     */         
/* 488 */         ParsedDateTime curStart = ParsedDateTime.fromUTCTime(cur.getStart());
/* 489 */         ParsedDateTime curEnd = ParsedDateTime.fromUTCTime(cur.getEnd());
/*     */         
/* 491 */         toRet.append(curStart.toString()).append('/').append(curEnd.toString()).append("\r\n");
/*     */       }
/*     */     }
/* 494 */     toRet.append("END:VFREEBUSY").append("\r\n");
/* 495 */     toRet.append("END:VCALENDAR").append("\r\n");
/* 496 */     return toRet.toString();
/*     */   }
/*     */   
/*     */   public String toVCalendarAsVEvents() throws ServiceException {
/* 500 */     StringWriter writer = new StringWriter();
/* 501 */     String publish = ZCalendar.ICalTok.PUBLISH.toString();
/* 502 */     long now = System.currentTimeMillis();
/*     */     
/* 504 */     writer.append("BEGIN:VCALENDAR").append("\r\n");
/* 505 */     writer.append("PRODID:").append("Zimbra-Calendar-Provider").append("\r\n");
/* 506 */     writer.append("VERSION:").append("2.0").append("\r\n");
/* 507 */     writer.append("METHOD:").append(publish).append("\r\n");
/*     */     
/* 509 */     String uidBase = "tmp_" + LdapUtil.generateUUID() + "_";
/* 510 */     int uidCount = 0;
/* 511 */     TimeZoneMap tzMap = new TimeZoneMap(ICalTimeZone.getUTC());
/* 512 */     for (Iterator<Interval> iter = iterator(); iter.hasNext();) {
/* 513 */       Interval cur = (Interval)iter.next();
/* 514 */       String status = cur.getStatus();
/*     */       
/* 516 */       if ((!status.equals("F")) && 
/*     */       
/* 518 */         (!status.equals("N")))
/*     */       {
/*     */ 
/*     */ 
/*     */ 
/* 523 */         Invite inv = new Invite(publish, tzMap, true);
/* 524 */         inv.setUid(uidBase + ++uidCount);
/* 525 */         inv.setSeqNo(0);
/* 526 */         inv.setDtStamp(now);
/* 527 */         inv.setDtStart(ParsedDateTime.fromUTCTime(cur.getStart()));
/* 528 */         inv.setDtEnd(ParsedDateTime.fromUTCTime(cur.getEnd()));
/* 529 */         inv.setFreeBusy(status);
/* 530 */         if (status.equals("T")) {
/* 531 */           inv.setStatus("TENT");
/* 532 */         } else if (status.equals("O")) {
/* 533 */           inv.setStatus("CONF");
/*     */         } else {
/* 535 */           inv.setStatus("CONF");
/*     */         }
/*     */         
/* 538 */         ZCalendar.ZComponent comp = inv.newToVComponent(false, true);
/*     */         try {
/* 540 */           comp.toICalendar(writer);
/*     */         } catch (IOException e) {
/* 542 */           throw ServiceException.FAILURE("can't write iCalendar object", e);
/*     */         }
/*     */       } }
/* 545 */     writer.append("END:VCALENDAR").append("\r\n");
/* 546 */     return writer.toString();
/*     */   }
/*     */   
/* 549 */   public String toString() { return this.mList.toString(); }
/*     */   
/* 551 */   public long getStartTime() { return this.mStart; }
/* 552 */   public long getEndTime() { return this.mEnd; }
/*     */   
/*     */   public static class FBInstance implements Comparable<FBInstance> {
/*     */     private long mStartTime;
/*     */     private long mEndTime;
/*     */     private int mApptId;
/*     */     private long mRecurIdDt;
/*     */     private String mFreeBusy;
/*     */     
/*     */     public FBInstance(String fb, long start, long end, int apptId, long recurIdDt) {
/* 562 */       this.mFreeBusy = fb;
/* 563 */       this.mStartTime = start;
/* 564 */       this.mEndTime = end;
/* 565 */       this.mApptId = apptId;
/* 566 */       this.mRecurIdDt = recurIdDt;
/*     */     }
/*     */     
/* 569 */     public long getStartTime() { return this.mStartTime; }
/* 570 */     public long getEndTime() { return this.mEndTime; }
/* 571 */     public int getApptId() { return this.mApptId; }
/* 572 */     public long getRecurIdDt() { return this.mRecurIdDt; }
/* 573 */     public String getFreeBusy() { return this.mFreeBusy; }
/*     */     
/*     */     public int compareTo(FBInstance other) {
/* 576 */       long startDiff = this.mStartTime - other.mStartTime;
/* 577 */       if (startDiff != 0L)
/* 578 */         return startDiff > 0L ? 1 : -1;
/* 579 */       long endDiff = this.mEndTime - other.mEndTime;
/* 580 */       if (endDiff != 0L)
/* 581 */         return endDiff > 0L ? 1 : -1;
/* 582 */       int idDiff = this.mApptId - other.mApptId;
/* 583 */       if (idDiff != 0)
/* 584 */         return idDiff;
/* 585 */       long ridDiff = this.mRecurIdDt - other.mRecurIdDt;
/* 586 */       if (ridDiff != 0L)
/* 587 */         return ridDiff > 0L ? 1 : -1;
/* 588 */       return this.mFreeBusy.compareTo(other.mFreeBusy);
/*     */     }
/*     */     
/*     */     public boolean equals(Object o) {
/* 592 */       if (!(o instanceof FBInstance)) {
/* 593 */         return false;
/*     */       }
/*     */       
/* 596 */       FBInstance other = (FBInstance)o;
/* 597 */       return (this.mStartTime == other.mStartTime) && (this.mEndTime == other.mEndTime) && (this.mApptId == other.mApptId) && (this.mRecurIdDt == other.mRecurIdDt) && (this.mFreeBusy.equals(other.mFreeBusy));
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   public static FreeBusy parse(ZCalendar.ZComponent comp)
/*     */     throws ServiceException
/*     */   {
/* 610 */     String name = null;
/* 611 */     ParsedDateTime dtStart = null;
/* 612 */     ParsedDateTime dtEnd = null;
/* 613 */     List<Interval> intervals = new ArrayList();
/* 614 */     TimeZoneMap tzmap = new TimeZoneMap(ICalTimeZone.getUTC());
/* 615 */     Iterator<ZCalendar.ZProperty> propIter = comp.getPropertyIterator();
/* 616 */     String fbStatus; while (propIter.hasNext()) {
/* 617 */       ZCalendar.ZProperty prop = (ZCalendar.ZProperty)propIter.next();
/* 618 */       ZCalendar.ICalTok tok = prop.getToken();
/* 619 */       if (tok != null)
/*     */       {
/* 621 */         switch (tok) {
/*     */         case DTSTART: 
/*     */           try {
/* 624 */             dtStart = ParsedDateTime.parse(prop, tzmap);
/*     */           } catch (ParseException e) {
/* 626 */             throw ServiceException.INVALID_REQUEST("bad DTSTART: " + prop.toString(), e);
/*     */           }
/*     */         case DTEND: 
/*     */           try
/*     */           {
/* 631 */             dtEnd = ParsedDateTime.parse(prop, tzmap);
/*     */           } catch (ParseException e) {
/* 633 */             throw ServiceException.INVALID_REQUEST("bad DTEND: " + prop.toString(), e);
/*     */           }
/*     */         
/*     */         case ORGANIZER: 
/* 637 */           ZOrganizer att = new ZOrganizer(prop);
/* 638 */           name = att.getAddress();
/* 639 */           break;
/*     */         case FREEBUSY: 
/* 641 */           fbStatus = "F";
/* 642 */           ZCalendar.ZParameter fbType = prop.getParameter(ZCalendar.ICalTok.FBTYPE);
/* 643 */           if (fbType != null)
/* 644 */             fbStatus = IcalXmlStrMap.sFreeBusyMap.toXml(fbType.getValue());
/* 645 */           List<String> vals = prop.getValueList();
/* 646 */           for (String fbVal : vals) {
/*     */             Period period;
/*     */             try {
/* 649 */               period = Period.parse(fbVal, ICalTimeZone.getUTC(), tzmap);
/*     */             } catch (ParseException e) {
/* 651 */               throw ServiceException.INVALID_REQUEST("bad period value: " + fbVal, e);
/*     */             }
/* 653 */             intervals.add(new Interval(period.getStart().getUtcTime(), period.getEnd().getUtcTime(), fbStatus));
/*     */           }
/*     */         }
/*     */         
/*     */       }
/*     */     }
/* 659 */     if (name == null)
/* 660 */       throw ServiceException.INVALID_REQUEST("VFREEBUSY missing ORGANIZER", null);
/* 661 */     if ((dtStart == null) || (dtEnd == null)) {
/* 662 */       throw ServiceException.INVALID_REQUEST("VFREEBUSY missing DTSTART/DTEND", null);
/*     */     }
/* 664 */     IntervalList ivalList = new IntervalList(dtStart.getUtcTime(), dtEnd.getUtcTime());
/* 665 */     for (Interval ival : intervals) {
/* 666 */       ivalList.addInterval(ival);
/*     */     }
/* 668 */     return new FreeBusy(name, ivalList, dtStart.getUtcTime(), dtEnd.getUtcTime());
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/fb/FreeBusy.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */